﻿
Imports System.Net
Imports std

Public Module rlogclient

    Public Class arguments
        Public Const commode As String = "commode"
        Public Const app As String = "app"
        Public Const msg As String = "msg"
        Public Const errtype As String = "errtype"
        Public Const errtypeChar As String = "errtypeChar"
        Public Const server As String = "server"
        Public Const port As String = "port"
    End Class

    Public Class commodeSelection
        Public Const tcp As String = "tcp"
        Public Const http As String = "http"
    End Class

    Friend app As String = Nothing
    Friend msg As String = Nothing
    Friend errtype As errorHandle.errorType = errorHandle.errorType.information
    Friend errtypeChar As Char = character.null
    Friend commode As String = Nothing
    Friend port As Int32 = 0
    Friend server As String = Nothing

    Public Sub main(ByVal iargs() As String)
        debugpause()

        Dim args As map(Of String, vector(Of String)) = Nothing
        argmgr.parse(iargs, args, True)
        Dim str As String = Nothing

        If Not argmgr.getfirstvalue(args, arguments.app, app, True) Then
            raiseError("do not get " + arguments.app + " value, ignore request.", errorHandle.errorType.user)
            Return
        End If

        If Not argmgr.getfirstvalue(args, arguments.msg, msg, True) Then
            raiseError("do not get " + arguments.msg + " value, ignore request.", errorHandle.errorType.user)
            Return
        End If

        If Not argmgr.getfirstvalue(args, arguments.server, server, True) Then
            raiseError("do not get " + arguments.server + " value, ignore request.", errorHandle.errorType.user)
            Return
        End If

        Dim errtypeInt As Int32
        If Not argmgr.getfirstvalue(args, arguments.errtype, str, True) _
            OrElse Not convertor.toint32(str, errtypeInt) _
            OrElse errtypeInt <= errorHandle.errorType.first _
            OrElse errtypeInt >= errorHandle.errorType.last Then
            raiseError("do not get valid " + arguments.errtype + " value, use default value " _
                       + Convert.ToString(errorHandle.errorType.information) + "." _
                       , errorHandle.errorType.user)
            errtype = errorHandle.errorType.information
        Else
            errtype = errtypeInt
        End If

        If Not argmgr.getfirstvalue(args, arguments.errtypeChar, str, True) _
            OrElse strlen(str) = 0 Then
            raiseError("do not get valid " + arguments.errtypeChar + " value, use default value." _
                       , errorHandle.errorType.user)
            errtypeChar = character.null
        Else
            errtypeChar = str(0)
        End If

        If Not argmgr.getfirstvalue(args, arguments.commode, commode, True) Then
            raiseError("do not get valid " + arguments.commode + " value, use default value " + commodeSelection.tcp _
                       , errorHandle.errorType.user)
            commode = commodeSelection.tcp
        End If

        If Not argmgr.getfirstvalue(args, arguments.port, str, True) OrElse Not convertor.toint32(str, port) Then
            raiseError("do not get valid " + arguments.port + " value, use default value " + Convert.ToString(npos) _
                       , errorHandle.errorType.user)
            port = npos
        End If

        Environment.Exit(Not comm())
    End Sub

    Public Function comm(ByRef commode As String, ByRef app As String, ByRef msg As String _
                         , ByRef errtype As errorHandle.errorType, ByRef errtypeChar As Char _
                         , ByRef server As String, ByVal port As Int32 _
                         , Optional ByVal needMsg As Boolean = False) As Boolean
        Dim httpmode As Boolean = strsame(commode, commodeSelection.http, False)
        If port = npos Then
            If httpmode Then
                port = rlogserve.arguments.defaultValues.httpport
            Else
                port = rlogserve.arguments.defaultValues.tcpport
            End If
        End If
        If httpmode Then
            Return httpcomm(app, msg, errtype, errtypeChar, server, port, needMsg)
        Else
            Return tcpcomm(app, msg, errtype, errtypeChar, server, port, needMsg)
        End If
    End Function

    Friend Function comm() As Boolean
        Return comm(commode, app, msg, errtype, errtypeChar, server, port, True)
    End Function

    Friend Function tcpcomm(ByRef app As String, ByRef msg As String _
                            , ByRef errtype As errorHandle.errorType, ByRef errtypeChar As Char _
                            , ByRef server As String, ByVal port As Int32 _
                            , ByVal needMsg As Boolean) As Boolean
        Dim talk As tcpTalk = Nothing
        talk = New tcpTalk()
        talk.host = server
        talk.port = port
        Dim queries As vector(Of pair(Of String, String)) = Nothing
        queries = New vector(Of pair(Of String, String))
        queries.push_back(make_pair(rlogserve.logkeys.app, app))
        queries.push_back(make_pair(rlogserve.logkeys.errorType, Convert.ToString(errtype)))
        queries.push_back(make_pair(Of String, String)(rlogserve.logkeys.errorTypeChar, errtypeChar))
        queries.push_back(make_pair(rlogserve.logkeys.msg, msg))
        If Not nettransDataInserter.keyvaluepair(talk.sendData(), queries, True) Then
            raiseError("cannot insert queries to talk.sendData(), ignore request.", errorHandle.errorType.exclamation)
            Return False
        End If

        If Not talk.talk() Then
            raiseError("cannot talk with server " + server + " , port " + Convert.ToString(port) _
                       , errorHandle.errorType.system)
            Return False
        End If

        If talk.receiveData Is Nothing OrElse talk.receiveData.fieldCount = 0 Then
            raiseError("do not get response from server " + server + ", port " + Convert.ToString(port) _
                        , errorHandle.errorType.exclamation)
            Return False
        End If

        Dim i As Int64
        For i = 0 To talk.receiveData.fieldCount - 1
            If needMsg Then
                raiseError(talk.receiveData.take(Of String)(i))
            End If
        Next

        talk.resetConnection()
        Return strsame(talk.receiveData.take(Of String)(0), rlogserve.logreply.success)
    End Function

    Friend Function tcpcomm() As Boolean
        Return tcpcomm(app, msg, errtype, errtypeChar, server, port, True)
    End Function

    Friend Function httpcomm(ByRef app As String, ByRef msg As String _
                            , ByRef errtype As errorHandle.errorType, ByRef errtypeChar As Char _
                            , ByRef server As String, ByVal port As Int32 _
                            , ByVal needMsg As Boolean) As Boolean
        On Error Resume Next

        Dim request As HttpWebRequest
        Dim address As String = network.httpAddressHeader + server + network.portMark _
                                + Convert.ToString(port) + network.pathSeperator
        request = HttpWebRequest.Create(address)
        request.Method = network.http.method.POST
        request.KeepAlive = False
        Dim query As String = Nothing
        query = rlogserve.logkeys.app + network.argumentNameValueSeparator + app + network.argumentSeperator _
                + rlogserve.logkeys.errorType + network.argumentNameValueSeparator + Convert.ToString(errtype) _
                + network.argumentSeperator _
                + rlogserve.logkeys.errorTypeChar + network.argumentNameValueSeparator + errtypeChar _
                + network.argumentSeperator _
                + rlogserve.logkeys.msg + network.argumentNameValueSeparator + msg
        Dim d() As Byte = Nothing
        d = encoding.utf8.GetBytes(query)
        request.ContentLength = d.Length()
        If Not writestream(request.GetRequestStream(), d) Then
            raiseError("cannot write query " + query + " to request stream, ignore request." _
                       , errorHandle.errorType.system)
            Return False
        Else
            closestream(request.GetRequestStream())
        End If

        Dim response As HttpWebResponse = Nothing
        response = request.GetResponse()
        If response Is Nothing Then
            raiseError("cannot get respone from httpserver.", errorHandle.errorType.exclamation)
            Return False
        End If
        raiseError("get response " + Convert.ToString(response.StatusCode) + " " + response.StatusDescription)
        Dim result As String = Nothing
        If Not readHttpResponse(response, result, address) Then
            raiseError("cannot get http response from server " + address, errorHandle.errorType.exclamation)
            Return False
        End If

        If needMsg Then
            raiseError(result)
        End If
        Return strsame(result, rlogserve.logreply.success, False)
    End Function

    Friend Function httpcomm() As Boolean
        Return httpcomm(app, msg, errtype, errtypeChar, server, port, True)
    End Function
End Module
